home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / C / Code Resources / Jims CDEFs 1.50 / CDEF Source / source / cdefVSlider.c < prev    next >
Encoding:
Text File  |  1995-11-13  |  23.4 KB  |  762 lines  |  [TEXT/KAHL]

  1. //------------------------- © 1994 - 1995 by James G. Stout ------------------------
  2. //    File    : cdefVSlider.c
  3. //    Date    : April 6, 1994
  4. //    Author    : Jim Stout
  5. //            :
  6. //    Purpose    : A slider CDEF modeled after the one in the Sound Control panel
  7. //            :
  8. //            : see cdefVSlider.h for more detail and variation codes
  9. //            :
  10. //            : If you find a use for this, I'd love to know about it.  Bug reports
  11. //            : are always interesting.
  12. //            :
  13. //            : Internet    : JimS@WRQ.COM(work hours, PST)
  14. //            : AppleLink   : WRQ            (daily)
  15. //            : CompuServe  : 73240,2052    (weekly or so)
  16. //            : AOL         : JasG        (weekly or so)
  17. //            : eWorld      : Jim Stout    (weekly or so)
  18. //----------------------------------------------------------------------------------
  19. //#define _DEBUGCDEF                    // comment this to build CDEF
  20.  
  21. #include "fatCDEF.h"
  22.  
  23. #include <Controls.h>
  24. #include <Fonts.h>
  25. #include <GestaltEqu.h>
  26. #include <Memory.h>
  27. #include <QDOffscreen.h>
  28. #include <ToolUtils.h>
  29. #include <Types.h>
  30. #include <Windows.h>
  31.  
  32.  
  33. #include "grayCDEF.h"
  34. #include "colorCDEF.h"
  35. #include "miscCDEF.h"
  36. #include "qdCDEF.h"
  37.  
  38. #include "cdefVslider.h"
  39.  
  40. #ifdef _DEBUGCDEF
  41. pascal long CDmain (short, ControlHandle, short, long);
  42.  
  43. pascal long CDmain (short varCode, ControlHandle theCtl, short message, long param)
  44. #else
  45.  
  46. //==================================================================================
  47. // CDEF entry point
  48. //==================================================================================
  49. pascal long main (short varCode, ControlHandle theCtl, short message, long param)
  50. #endif
  51. {
  52.     long        ret = 0L;
  53.     SignedByte    cState, dState;
  54.     
  55. #include "fatEntry.c"
  56.     
  57.     cState = HGetState((Handle)theCtl);
  58.     HLock((Handle)theCtl);
  59.     if((**theCtl).contrlData) {
  60.         dState = HGetState((**theCtl).contrlData);
  61.         HLock((**theCtl).contrlData);
  62.     }
  63.     
  64.     switch(message) {
  65.         case initCntl:
  66.             doInit(theCtl);
  67.             if((**theCtl).contrlData) {
  68.                 dState = HGetState((**theCtl).contrlData);
  69.                 HLock((**theCtl).contrlData);
  70.             }
  71.         break;
  72.         case dispCntl:
  73.             doDisp(theCtl);
  74.         break;
  75.         case drawCntl:
  76.             if ((**theCtl).contrlVis != 0 &&
  77.                 ((WindowPeek)(**theCtl).contrlOwner)->visible) {
  78.                 doDraw(theCtl, varCode);
  79.             }
  80.         break;
  81.         case testCntl:
  82.             ret = doTest (theCtl, varCode, param);
  83.         break;
  84.         case calcCRgns:
  85.             RectRgn((RgnHandle)(param & 0x7fffffffL), &(**theCtl).contrlRect);
  86.         break;
  87.         case calcCntlRgn:
  88.         case calcThumbRgn:
  89.             RectRgn((RgnHandle)(param), &(**theCtl).contrlRect);
  90.         break;
  91.     }
  92.  
  93.     if((**theCtl).contrlData)
  94.         HSetState((**theCtl).contrlData, dState);
  95.     HSetState((Handle)theCtl, cState);
  96.     
  97.  
  98. #include "fatExit.c"
  99.     
  100.     return (ret);
  101. }
  102.  
  103. //==================================================================================
  104. //    Initialize our control data
  105. //==================================================================================
  106.  
  107. static void doInit (ControlHandle theCtl)
  108. {
  109.     short        scaleSize;
  110.     Rect        scaleRect;
  111.     CDEFHandle    hCDEF;
  112.     
  113. //----------------------------------------------------------------------------------
  114. // check for a reasonably sized scale
  115. //----------------------------------------------------------------------------------
  116.     
  117.     scaleSize = (**theCtl).contrlRfCon;
  118.     if(scaleSize < 2 || scaleSize > 20)            // must be at least 2 units high
  119.         scaleSize = 7;                            // … 7 is like the Sound Control panel
  120.         
  121. //----------------------------------------------------------------------------------
  122. // force the scale rect to the size we want, it'll be clipped to the control Rect
  123. //----------------------------------------------------------------------------------
  124.     
  125.     scaleRect = (**theCtl).contrlRect;
  126.     scaleRect.right = scaleRect.left + 42;
  127.     scaleRect.bottom = scaleRect.top + scaleSize*12+21;
  128.     
  129. //----------------------------------------------------------------------------------
  130. // force the min & max as well
  131. //----------------------------------------------------------------------------------
  132.     
  133.     (**theCtl).contrlMin = 0;
  134.     (**theCtl).contrlMax = scaleSize*12;        // number of pixels in scale
  135.     (**theCtl).contrlRfCon = 0;
  136.     
  137.     hCDEF = (CDEFHandle)NewHandle(sizeof(CDEFData));
  138.     if(hCDEF) {
  139.         (**hCDEF).pDepth = 1;                    // filled in in doDraw()
  140.         (**hCDEF).offPort = 0;
  141.         (**hCDEF).scaleSize = scaleSize;
  142.         (**hCDEF).scaleRect = scaleRect;
  143.         (**hCDEF).qdVers = getQDVers();
  144.         
  145.         (**theCtl).contrlData = (Handle)hCDEF;
  146.     }
  147.     else
  148.         (**theCtl).contrlData = 0;
  149. }
  150.  
  151. //==================================================================================
  152. //    Get rid of our control data
  153. //==================================================================================
  154.  
  155. static void doDisp        (ControlHandle theCtl)
  156. {
  157.     CDEFHandle    hCDEF;
  158.     BitMap        *theBits;
  159.     
  160.     hCDEF = (CDEFHandle)(**theCtl).contrlData;
  161.     if(hCDEF) {
  162.         if((**hCDEF).offPort) {
  163.             if(((**hCDEF).offPort->portVersion & 0x8000) != 0) {    // offPort is GWorld
  164.                 DisposeGWorld((**hCDEF).offPort);                
  165.             }
  166.             else {                                                    // offport is bitmap
  167.                 theBits = &((GrafPtr)(**hCDEF).offPort)->portBits;
  168.                 DisposePtr((*theBits).baseAddr);
  169.                 ClosePort((GrafPtr)(**hCDEF).offPort);
  170.                 DisposePtr((Ptr)(**hCDEF).offPort);
  171.             }
  172.         }
  173.             
  174.         HUnlock((Handle)hCDEF);
  175.         DisposeHandle((Handle)hCDEF);
  176.         (**theCtl).contrlData = 0;
  177.     }
  178. }
  179.  
  180. //==================================================================================
  181. //    Test to see if the mouse was pressed in the control thumb and 
  182. //  drag accordingly
  183. //==================================================================================
  184.  
  185. static long doTest (ControlHandle theCtl, short varCode, long param)
  186. {
  187.     Rect    rThumb, rScale;
  188.     Point    p;
  189.     long    ret=0,secs;
  190.     short    partCode;
  191.     CDEFHandle    hCDEF;
  192.     
  193.     hCDEF = (CDEFHandle)(**theCtl).contrlData;
  194.     if(!hCDEF)
  195.         return(ret);
  196.  
  197.     partCode = (**theCtl).contrlHilite;
  198.         
  199.     rScale = (**hCDEF).scaleRect;
  200.     
  201. //----------------------------------------------------------------------------------
  202. // get the thumb rect, calculated from control value
  203. //----------------------------------------------------------------------------------
  204.     getThumbRect(theCtl, &rThumb, &rScale);
  205.     
  206.     rScale.left+=17;                                    // inset for active area
  207.     InsetRect(&rScale,8,5);
  208.     
  209.     p.h = LoWord(param);
  210.     p.v = HiWord(param);
  211.     
  212.     if(PtInRect(p, &rThumb)) {                            // click in thumb?
  213.         ret = 1;
  214.         dragThumb(theCtl, varCode, param);
  215.     }
  216.     else
  217.     if(PtInRect(p, &rScale)) {                            // click in scale?
  218.         if(p.v < rThumb.bottom)
  219.             ret = 2;                                    // decrease
  220.         else
  221.         if(p.v > rThumb.top)
  222.             ret = 3;                                    // increase
  223.             
  224.         if(partCode == ret) {
  225.             scaleClick(theCtl, varCode, (short)ret);
  226.             Delay(6L, & secs);
  227.         }
  228.     }
  229.     return(ret);
  230. }
  231.  
  232. //==================================================================================
  233. // Respond to a mouse down in our "thumb", track the mouse to reposition the thumb,
  234. // set a new control value and call the actionProc (if any).
  235. //==================================================================================
  236. static void dragThumb (ControlHandle theCtl, short varCode, long param)
  237. {
  238.     short    units,newVal,snap,maxDrag,minDrag;
  239.     Rect    rThumb, rScale;
  240.     Point    p,oldPt;
  241.     
  242.     rScale = (**(CDEFHandle)(**theCtl).contrlData).scaleRect;
  243.     getThumbRect(theCtl, &rThumb, &rScale);
  244.     
  245.     units = ((rScale.bottom-rScale.top)-21)/12;
  246.     p.h = LoWord(param);
  247.     p.v = oldPt.v = HiWord(param);
  248.     
  249.     if(PtInRect(p, &rThumb)) {
  250.         maxDrag = rScale.bottom - 4 - (rThumb.bottom - p.v);
  251.         minDrag = rScale.top + 4 + (p.v - rThumb.top);
  252.         
  253.         while (StillDown()) {
  254.             if(oldPt.v != p.v) {                            // mouse moved
  255.                 OffsetRect(&rThumb, 0, (p.v-oldPt.v));        // move the thumb
  256.                 if(rThumb.top < rScale.top+5)                // pin to top of scale
  257.                     OffsetRect(&rThumb, 0, rScale.top - rThumb.top+5); 
  258.                 else
  259.                 if(rThumb.bottom > rScale.bottom-5)            // pin to bottom of scale
  260.                     OffsetRect(&rThumb, 0, rScale.bottom - rThumb.bottom-5); 
  261.                     
  262.                 newVal = (rScale.top - rThumb.top)+units*12+5;
  263.                 if(newVal != (**theCtl).contrlValue) {
  264.                     (**theCtl).contrlValue = newVal;
  265.                     doDraw(theCtl, varCode);
  266.                     if((**theCtl).contrlAction != nil)
  267.                         CallControlActionProc((**theCtl).contrlAction, 
  268.                                                 theCtl, 1);
  269.                 }
  270.                 if(p.v > minDrag && p.v < maxDrag)            // track move
  271.                     oldPt.v = p.v;    
  272.             }
  273.             GetMouse(&p);
  274.         }
  275.     }
  276.  
  277. //----------------------------------------------------------------------------------
  278. // adjust the control value & redraw if necessary
  279. //----------------------------------------------------------------------------------
  280.  
  281.     if(!(varCode & thumbNoSnap)) {
  282.         snap = (rThumb.top-rScale.top-5)%12;
  283.         if(snap) {
  284.             if(snap >= 7)
  285.                 OffsetRect(&rThumb, 0, 12-snap);
  286.             else
  287.                 OffsetRect(&rThumb, 0, -snap);
  288.         }
  289.     }
  290.     (**theCtl).contrlValue = (rScale.top - rThumb.top)+units*12+5;
  291.     doDraw(theCtl, varCode);
  292.     if((**theCtl).contrlAction != nil)
  293.         CallControlActionProc((**theCtl).contrlAction, theCtl, 1);
  294. }
  295.  
  296. //==================================================================================
  297. // Adjust the control after detecting a click in the scale instead of the thumb -
  298. // set a new control value and call the actionProc (if any).
  299. //==================================================================================
  300. static void scaleClick (ControlHandle theCtl, short varCode, 
  301.                             short partCode)
  302. {
  303.     Rect    rThumb, rScale;
  304.     short    incr,newVal,units;
  305.  
  306.     rScale = (**(CDEFHandle)(**theCtl).contrlData).scaleRect;
  307.     getThumbRect(theCtl, &rThumb, &rScale);
  308.     
  309.     units = ((rScale.bottom-rScale.top)-21)/12;
  310.     if(varCode & thumbNoSnap)
  311.         incr = 1;
  312.     else
  313.         incr = 12;
  314.         
  315.     if(partCode == 2) {
  316.         OffsetRect(&rThumb, 0, -incr);
  317.     }
  318.     else 
  319.     if(partCode == 3) {
  320.          OffsetRect(&rThumb, 0, incr);
  321.     }    
  322.  
  323.     if(rThumb.top < rScale.top+5)                            // pin to top of scale
  324.         OffsetRect(&rThumb, 0, rScale.top - rThumb.top+5); 
  325.     else
  326.     if(rThumb.bottom > rScale.bottom-5)                        // pin to bottom of scale
  327.         OffsetRect(&rThumb, 0, rScale.bottom - rThumb.bottom-5);
  328.                     
  329.     newVal = (rScale.top - rThumb.top)+units*12+5;
  330.     
  331.     if(newVal != (**theCtl).contrlValue) {
  332.         (**theCtl).contrlValue = newVal;
  333.         doDraw(theCtl, varCode);
  334.         if((**theCtl).contrlAction != nil)
  335.             CallControlActionProc((**theCtl).contrlAction, theCtl, partCode);
  336.     }    
  337. }
  338.  
  339. //==================================================================================
  340. //    Calculate the thumb location from the control value
  341. //==================================================================================
  342.  
  343. static void getThumbRect(ControlHandle theCtl, Rect *rThumb, Rect *rScale)
  344. {
  345.     short    v;
  346.     
  347.     SetRect(rThumb, 0, 0, 23, 11);
  348.     v = (rScale)->bottom - 16 - (**theCtl).contrlValue;
  349.     OffsetRect(rThumb, (rScale)->left+18,v);
  350. }
  351.  
  352. //==================================================================================
  353. //    Draw both the scale and thumb into one bitmap
  354. //==================================================================================
  355.  
  356. Boolean drawParts (ControlHandle theCtl, short varCode, Rect *rThumb)
  357. {
  358.     Rect            rScale, r;
  359.     Boolean            inColor = false, haveGray = false;
  360.     RGBColor        saveFore, saveBack, grayColor, tingeColor, fillColor;
  361.     RGBColor        scaleColor = {56797, 56797, 56797};
  362.     short            h,v,inx;
  363.     char            c,c1;    
  364.     CDEFHandle        hCDEF;
  365.         
  366.     hCDEF = (CDEFHandle)(**theCtl).contrlData;            // already locked
  367.     if(hCDEF) {
  368. //----------------------------------------------------------------------------------
  369. // set up our drawing rects
  370. //----------------------------------------------------------------------------------
  371.  
  372.         SetRect(&rScale, 0, 0, 42, (**hCDEF).scaleSize*12+21);
  373.         r = rScale;
  374.                 
  375. //----------------------------------------------------------------------------------
  376. //    Set colors - either cFrameColor or grayed version of cFrameColor if inactive
  377. //----------------------------------------------------------------------------------
  378.  
  379.         if((**hCDEF).pDepth > 2) {
  380.             inColor = true;
  381.             setPartColor(theCtl, cFrameColor, true);
  382.         }
  383.  
  384.         if((**theCtl).contrlHilite == 0xFF) {            // inactive control
  385.             if(inColor) {                                // try to draw it in
  386.                 haveGray = getGray(&grayColor);            // gray
  387.                 if(haveGray)
  388.                     RGBForeColor(&grayColor);
  389.             }
  390.         }
  391.  
  392.         if(inColor)
  393.             saveColors(&saveFore, &saveBack);            // saveFore may be gray...
  394.         
  395. //----------------------------------------------------------------------------------
  396. // draw the scale into this offport
  397. //----------------------------------------------------------------------------------
  398.         
  399.         r.left+=23;                                        // rect for the scale
  400.         r.right-=6;
  401.         ForeColor(whiteColor);                            // make it white
  402.         PaintRoundRect(&r, 14, 10);
  403.         
  404.         if(inColor)
  405.             RGBForeColor(&saveFore);
  406.         else
  407.             ForeColor(blackColor);
  408.         BackColor(whiteColor);
  409.                 
  410.         FrameRoundRect(&r, 14, 10);                        // frame outer rect
  411.         InsetRect(&r, 2, 2);                            // now fill inner rect
  412.         
  413.         if(!(varCode & scaleNoFill)) {
  414.             if(inColor) {
  415.                   setPartColor(theCtl, cBodyColor, true);
  416.                   GetForeColor(&fillColor);
  417.                   if(fillColor.red == 65535 && 
  418.                       fillColor.green == 65535 &&
  419.                       fillColor.blue == 65535) {
  420.                       ForeColor(blackColor);
  421.                   }
  422.                   if(haveGray) {                            // must be inactive
  423.                       if(getGray(&fillColor)) {
  424.                           RGBForeColor(&fillColor);
  425.                       }
  426.                   }
  427.             }
  428.             PenPat( (ConstPatternParam) "\xAA\x55\xAA\x55\xAA\x55\xAA\x55");
  429.             PaintRoundRect(&r, 11, 9);
  430.             PenPat( (ConstPatternParam) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF");
  431.         }
  432.         if(inColor)
  433.             RGBForeColor(&saveFore);
  434.         else
  435.             ForeColor(blackColor);
  436.          FrameRoundRect(&r, 11, 9);                        // frame inner rect
  437.          
  438. //----------------------------------------------------------------------------------
  439. // erase the corners of the inner round rect - the hard way
  440. //----------------------------------------------------------------------------------
  441.     
  442.          ForeColor(whiteColor);
  443.          MoveTo(r.left+2, r.top);
  444.          Line(0, 0);
  445.          Move(4, 0);
  446.          Line(0, 0);
  447.          MoveTo(r.left+2, r.bottom-1);
  448.          Line(0, 0);
  449.          Move(4, 0);
  450.          Line(0, 0);
  451.     
  452. //----------------------------------------------------------------------------------
  453. // draw tick marks for scale
  454. //----------------------------------------------------------------------------------
  455.         if(inColor) {
  456.             RGBBackColor(&saveBack);
  457.             setPartColor(theCtl, cTextColor, true);
  458.             if(haveGray) {                                    // inactive
  459.                 if(getGray(&grayColor))
  460.                     RGBForeColor(&grayColor);
  461.             }
  462.         }
  463.         else
  464.              ForeColor(blackColor);
  465.             
  466.         if(!(varCode & scaleBlank)) {            
  467.              MoveTo(r.left - 8, r.bottom - 9);
  468.              for(inx = 0; inx<=(**hCDEF).scaleSize; inx++) {
  469.                  Line(3, 0);
  470.                  Move(-3, -12);
  471.              }
  472.  
  473. //----------------------------------------------------------------------------------
  474. // draw digits next to tick marks
  475. //----------------------------------------------------------------------------------
  476.  
  477.              TextFont(geneva);                    
  478.             TextSize(9);
  479.             v = r.bottom-4;
  480.             h = r.left-18;
  481.             c = c1 = '0';
  482.             for(inx=0;inx<=(**hCDEF).scaleSize;inx++) {
  483.                 if(!(inx%10) && inx) {
  484.                     c = '0';
  485.                     c1++;
  486.                 }
  487.                 MoveTo (h, v);
  488.                 DrawChar(c);
  489.                 if(inx>9) {
  490.                     h-=6;
  491.                     MoveTo(h,v);
  492.                     DrawChar(c1);
  493.                     h+=6;
  494.                 }
  495.                 v-=12;
  496.                 c++;
  497.             }
  498.         }
  499.         
  500. //----------------------------------------------------------------------------------
  501. //    Draw 3D version of scale
  502. //----------------------------------------------------------------------------------
  503.  
  504.         if(varCode & ctl3D && inColor) {
  505.             RGBForeColor(&scaleColor);
  506.             RGBBackColor(&saveBack);
  507.             
  508. //----------------------------------------------------------------------------------
  509. // fill center of scale with light gray
  510. //----------------------------------------------------------------------------------
  511.  
  512.             rScale.left+=17;
  513.             InsetRect(&rScale,9,4);
  514.             SetRect(&r, rScale.left+2,rScale.top-1,
  515.                         rScale.right-2,rScale.top+1);
  516.             PaintRect(&r);
  517.             SetRect(&r, rScale.left+2,rScale.bottom-1,
  518.                         rScale.right-2,rScale.bottom+1);
  519.             PaintRect(&r);
  520.             PaintRect(&rScale);
  521.             
  522. //----------------------------------------------------------------------------------
  523. // draw 3D shadow along bottom & right
  524. //----------------------------------------------------------------------------------
  525.  
  526.               setPartColor(theCtl, cTingeLight, true);
  527.               GetForeColor(&tingeColor);
  528.               tingeColor.red-=13107;
  529.               tingeColor.green-=13107;
  530.               tingeColor.blue-=13107;
  531.               RGBForeColor(&tingeColor);
  532.               MoveTo(rScale.left+2, rScale.bottom);
  533.               Line(2,0);
  534.               Line(0,-1);
  535.               Line(2,0);
  536.               LineTo(rScale.right-1, rScale.top);
  537.         }
  538.  
  539. //----------------------------------------------------------------------------------            
  540. // draw the Thumb into the offPort
  541. //----------------------------------------------------------------------------------
  542.  
  543.         ForeColor(whiteColor);                                // thumb defaults to
  544.         PaintRoundRect(rThumb, 7, 11);                        // white background
  545.         if(inColor)
  546.               RGBForeColor(&saveFore);                        // with cFrameColor
  547.         else
  548.             ForeColor(blackColor);
  549.         FrameRoundRect(rThumb, 7, 11);
  550.         
  551.         MoveTo(rThumb->left+1, rThumb->top+2);
  552.         Line(19, 0);
  553.         MoveTo(rThumb->left+1, rThumb->bottom-3);
  554.         Line(19, 0);
  555.         
  556. //----------------------------------------------------------------------------------
  557. //    Draw 3D version of thumb
  558. //----------------------------------------------------------------------------------
  559.     
  560.           if(varCode & ctl3D  && inColor) {
  561.             RGBForeColor(&scaleColor);
  562.               InsetRect(rThumb, 1, 3);
  563.               PaintRect(rThumb);
  564.               MoveTo((*rThumb).left+1, (*rThumb).top-2);
  565.               LineTo((*rThumb).right-2, (*rThumb).top-2);
  566.               MoveTo((*rThumb).left+1, (*rThumb).bottom+1);
  567.               LineTo((*rThumb).right-2, (*rThumb).bottom+1);
  568.               
  569. //----------------------------------------------------------------------------------
  570. // draw the 3D shadow in a grayed cTingeColor
  571. //----------------------------------------------------------------------------------
  572.  
  573.               RGBForeColor(&tingeColor);
  574.               MoveTo((*rThumb).left, (*rThumb).bottom-1);
  575.               LineTo((*rThumb).right-1, (*rThumb).bottom-1);
  576.               LineTo((*rThumb).right-1, (*rThumb).top);
  577.               MoveTo((*rThumb).right-2, (*rThumb).bottom-2);
  578.               LineTo((*rThumb).right-2, (*rThumb).bottom-2);
  579.           }
  580.           else {                                                // colorize center part
  581.               if(inColor) {                                    // of thumb
  582.                   ForeColor(whiteColor);
  583.                   setPartColor(theCtl, cThumbColor, true);
  584.                   InsetRect(rThumb, 1, 3);
  585.                   PaintRect(rThumb);
  586.               }
  587.           }
  588.       }
  589.       return(haveGray);
  590. }
  591.  
  592. //==================================================================================
  593. //    Draw the control, it is made up from the scale bitmap and the thumb bitmap
  594. //    which are assembled into an offscreen bitmap in "drawParts".  Now, we blit it
  595. //  to our onscreen port.
  596. //==================================================================================
  597.  
  598. static void doDraw (ControlHandle theCtl, short varCode)
  599. {
  600.     Rect            offRect, rThumb, rScale;
  601.     RgnHandle        saveClip, newClip;
  602.     BitMap            *offBits;
  603.     PixMapHandle    pmHdl;
  604.     CGrafPtr        savePort;
  605.     GDHandle        saveGDev;
  606.     PenState        savePen;
  607.     Boolean            inactive = false, haveGray = false, inColor = false, haveGW = false;
  608.     RGBColor        saveFore,saveBack;
  609.     CDEFHandle        hCDEF;
  610.     
  611.     hCDEF = (CDEFHandle)(**theCtl).contrlData;                // already locked
  612.     if(hCDEF) {
  613.     
  614. //----------------------------------------------------------------------------------    
  615. // If control has been moved we need to update our rect
  616. //----------------------------------------------------------------------------------
  617.  
  618.         rScale = (**theCtl).contrlRect;
  619.         rScale.right = rScale.left + 42;
  620.         rScale.bottom = rScale.top + (**hCDEF).scaleSize*12+21;
  621.     
  622.         (**hCDEF).scaleRect = rScale;
  623.         (**theCtl).contrlData = (Handle)hCDEF;
  624.     
  625. //----------------------------------------------------------------------------------    
  626. // Create or update our GWorld
  627. //----------------------------------------------------------------------------------
  628.     
  629.         (**hCDEF).pDepth = getOff(&(**hCDEF).offPort, &(**theCtl).contrlRect);
  630.         
  631.         if((**hCDEF).pDepth == 0)                            // oh… oh…
  632.             return;                                        
  633.                 
  634.         if(((**hCDEF).offPort->portVersion & 0x8000) != 0) {
  635.             haveGW = true;                                    // have a GWorld
  636.             pmHdl  = getLockedPixels(&(**hCDEF).offPort, (**hCDEF).qdVers);
  637.             if(!pmHdl)
  638.                 return;                                        // nuts…
  639.         }
  640.  
  641. //----------------------------------------------------------------------------------
  642. //    Do the clip region properly.  Thanks Ari!
  643. //----------------------------------------------------------------------------------
  644.  
  645.         saveClip = NewRgn();
  646.         GetClip(saveClip);
  647.         
  648.         newClip = NewRgn();
  649.         RectRgn(newClip, &(**theCtl).contrlRect);
  650.         SectRgn(saveClip, newClip, newClip);
  651.         
  652.         if(EmptyRgn(newClip)) {                                // if empty, don't waste
  653.             DisposeRgn(saveClip);                            // time drawing...
  654.             DisposeRgn(newClip);
  655.             return;
  656.         }
  657.     
  658.         SetClip(newClip);
  659. //----------------------------------------------------------------------------------                    
  660. // Calculate size for offRect (scale) & position the thumb rect
  661. //----------------------------------------------------------------------------------
  662.         
  663.         SetRect(&offRect, 0, 0, 42, (**hCDEF).scaleSize*12+21);
  664.         rScale = (**hCDEF).scaleRect;
  665.         
  666.         SetRect(&rThumb, 0, 0, 23, 11);
  667.         OffsetRect(&rThumb, 18, offRect.bottom - 16 - (**theCtl).contrlValue);
  668.         
  669. //----------------------------------------------------------------------------------
  670. // Initialize and set for drawing into offScreen port
  671. //----------------------------------------------------------------------------------
  672.  
  673.           if((**theCtl).contrlHilite == 0xFF)                    // inactive control
  674.             inactive = true;
  675.             
  676.         if((**hCDEF).pDepth > 2) {                            // save onscreen    
  677.             inColor = true;                                    // colors
  678.             saveColors(&saveFore, &saveBack);
  679.         }
  680.         
  681.         if(haveGW) {                                        // we have a pixMap    
  682.             GetGWorld(&savePort, &saveGDev);
  683.             SetGWorld((**hCDEF).offPort, nil);
  684.             offBits = (BitMap *)*pmHdl;    
  685.             if((**(*savePort).bkPixPat).patType != 0 &&
  686.                 (savePort->portVersion & 0x8000) != 0)
  687.                 BackPixPat((*savePort).bkPixPat);
  688.         }
  689.         else {                                                // we have a bitMap    
  690.             GetPort((GrafPtr*)&savePort);
  691.             SetPort((GrafPtr)(**hCDEF).offPort);        
  692.             offBits = (BitMap *)&((GrafPtr)(**hCDEF).offPort)->portBits;
  693.         }
  694.         
  695.         if(inColor) {                                        // onscreen colors in
  696.             RGBForeColor(&saveFore);                        // offscreen port
  697.             RGBBackColor(&saveBack);
  698.         }
  699.  
  700. //----------------------------------------------------------------------------------
  701. //    Erase background of offscreen port - pay attention to origin so patterned
  702. //    backgrounds are aligned
  703. //----------------------------------------------------------------------------------
  704.  
  705.         SetOrigin((**theCtl).contrlRect.left, (**theCtl).contrlRect.top);
  706.         EraseRect(&(**theCtl).contrlRect);
  707.         SetOrigin(0,0);
  708.         
  709. //----------------------------------------------------------------------------------    
  710. // draw the control parts into the offscreen port
  711. //----------------------------------------------------------------------------------
  712.     
  713.         haveGray = drawParts (theCtl, varCode, &rThumb);
  714.     
  715. //----------------------------------------------------------------------------------    
  716. // Now, set up to copy the offscreen bit/pixmap to the screen
  717. //----------------------------------------------------------------------------------
  718.         if(haveGW)
  719.             SetGWorld(savePort, saveGDev);
  720.         else
  721.             SetPort((GrafPtr)savePort);
  722.         
  723.         if(inColor) {
  724.             ForeColor(blackColor);
  725.             BackColor(whiteColor);
  726.         }
  727.  
  728. //----------------------------------------------------------------------------------        
  729. // now copy it to the onscreen port and restore our colors
  730. //----------------------------------------------------------------------------------
  731.     
  732.         CopyBits(offBits,
  733.                 &((GrafPtr)savePort)->portBits,
  734.                 &offRect,
  735.                 &rScale,
  736.                 srcCopy, nil);
  737.         
  738.         if(haveGW) {
  739.             unlockPixels(pmHdl, (**hCDEF).qdVers);
  740.             DisposeGWorld((**hCDEF).offPort);
  741.             (**hCDEF).offPort = 0;
  742.         }
  743.                 
  744.         if(inColor)
  745.             restoreColors(&saveFore, &saveBack);
  746.  
  747. //----------------------------------------------------------------------------------
  748. // if we failed to get an inactive gray color, do it the old way
  749. //----------------------------------------------------------------------------------
  750.  
  751.         if(inactive & !haveGray) {                    // use the old way of drawing
  752.             GetPenState(&savePen);                    // an inactive control
  753.             PenMode(patBic);
  754.             PenPat( (ConstPatternParam) "\xAA\x55\xAA\x55\xAA\x55\xAA\x55");
  755.             PaintRect(&(**theCtl).contrlRect);
  756.             SetPenState(&savePen);
  757.         }
  758.         SetClip(saveClip);
  759.         DisposeRgn(saveClip);
  760.         DisposeRgn(newClip);
  761.     }
  762. }